package gobase

/***
BE:
  0xAABBCCDDEEFF => 0000AABBCCDDEEFF
LE:
  0x00490001 => 01 00 49 00
*/

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	"math"
	"strings"
	"unsafe"
)

var (
	SPACE_BYTES []byte = []byte(" ")
)

/*
*

	abc=> cba
*/
func ReverseBytes(buf []byte) {
	for i, j := 0, len(buf)-1; i < j; {
		buf[i], buf[j] = buf[j], buf[i]
		i++
		j--
	}
}

func SwapBytes(buf []byte) []byte {
	l := len(buf)
	idx := 0
	var tmp byte
	for {
		if idx >= l-idx-1 {
			break
		}
		tmp = buf[idx]
		buf[idx] = buf[l-idx-1]
		buf[l-idx-1] = tmp
		idx++
	}
	return buf
}

func CloneBytesEx(src []byte, offset int, l int) []byte {
	if l == 0 {
		src = src[offset:]
		l = len(src)
	}
	cpyBuf := make([]byte, l, l)
	copy(cpyBuf, src[offset:])
	return cpyBuf
}

func CloneBytes(src []byte, offset int, l int) []byte {
	if l == 0 {
		return append([]byte{}, src[offset:]...)
	}
	endl := MinInt(offset+l, len(src))
	return append([]byte{}, src[offset:endl]...)
}

/// 和c的写入一致
/*
   char buf[1024];
   double lng = 114.1234;
   memcpy(buf, &lng, 8);

   printbuf(buf, 0, 8);

   output: 228 20 29 201 229 135 92 64

   utils.WriteBuf_Float64(lng, buf[1:])
*/

func WriteBuf_LE_Float64(val float64, outBuf []byte) {
	bits := math.Float64bits(val)
	binary.LittleEndian.PutUint64(outBuf, bits)
}

func WriteBuf_BE_Float64(val float64, outBuf []byte) {
	bits := math.Float64bits(val)
	binary.BigEndian.PutUint64(outBuf, bits)
}

func Bool2Byte(v bool) byte {
	if v {
		return 1
	} else {
		return 0
	}
}

func Bool2Str(v bool) string {
	if v {
		return "true"
	} else {
		return "false"
	}
}

func InsertBuf(buf []byte, startidx int, val []byte) (newBuf []byte) {
	// 延长切片长度
	newBuf = append(buf, val...)

	// 把数据推后
	copy(newBuf[startidx+len(val):], newBuf[startidx:])

	// 插入新数据
	copy(newBuf[startidx:], val)
	return
}

func DeleteBuf(buf []byte, startidx, n int) (newBuf []byte) {
	j := startidx + n
	if j < len(buf) {
		newBuf = append(buf[:startidx], buf[j:]...)
	} else {
		newBuf = buf[:startidx]
	}
	return
}

func XorBytes(buf []byte) byte {
	rval := byte(0)
	for i := 0; i < len(buf); i++ {
		rval = rval ^ buf[i]
	}
	return rval
}

func CheckByteIn(v byte, sets ...byte) bool {
	for i := 0; i < len(sets); i++ {
		if sets[i] == v {
			return true
		}
	}
	return false
}

func TrimPrefixBuf(buf []byte, prefix []byte) (rval []byte, changed bool) {
	if bytes.HasPrefix(buf, prefix) {
		return buf[len(prefix):], true
	} else {
		return buf, false
	}
}

func TrimPrefixBytes(buf []byte, byteset ...byte) []byte {
	for i := 0; i < len(buf); i++ {
		if !CheckByteIn(buf[i], byteset...) {
			return buf[i:]
		}
	}
	return buf[0:0]
}

func TrimRightBytes(buf []byte, rightByte ...byte) []byte {
	for i := len(buf) - 1; i >= 0; i-- {
		if !CheckByteIn(buf[i], rightByte...) {
			return buf[0 : i+1]
		}
	}
	return buf[0:0]
}

/*
*

	slice[:j]  // 从最开头切到 j(不包含 j)
*/
func TrimRightByte(buf []byte, rightByte byte) []byte {
	for i := len(buf) - 1; i >= 0; i-- {
		if buf[i] != rightByte {
			return buf[0 : i+1]
		}
	}
	return buf[0:0]
}

// **** 兼容RTCM中的位

const (
	U8_1    byte   = 1
	U8_0    byte   = 0
	U8_MAX  byte   = ^U8_0
	U32_1   uint32 = 1
	U32_0   uint32 = 0
	U64_0   uint64 = 0
	I64_1   int64  = 1
	U64_1   uint64 = 1
	U64_MAX uint64 = ^U64_0
)

// 第一位作为符号位
func GetBitI32(buf []byte, startBitN int, l int) int32 {
	ru := GetBitU(buf, startBitN, l)
	if l <= 0 || l >= 32 {
		return int32(ru)
	}

	if ru&uint32(U32_1<<uint(l-1)) == 0 {
		return int32(ru)
	}

	v := ^U32_0

	v = uint32(v << uint(l))
	rval := ru | v

	return int32(rval)
}

// 第一位作为符号位
func GetBitI64(buf []byte, startBitN int, l int) int64 {
	ru := GetBitU64(buf, startBitN, l)
	if l <= 0 || l >= 64 {
		return int64(ru)
	}

	if ru&uint64(U64_1<<uint(l-1)) == 0 {
		return int64(ru)
	}

	v := ^U64_0

	v = uint64(v << uint(l))
	rval := ru | v

	return int64(rval)
}

func GetBitI8(buf []byte, startBitN int, l int) int8 {
	return int8(GetBitI32(buf, startBitN, l))
}

func GetBitI16(buf []byte, startBitN int, l int) int16 {
	return int16(GetBitI32(buf, startBitN, l))
}

func GetBitU(buf []byte, startBitN int, l int) uint32 {
	return uint32(GetBitU64(buf, startBitN, l))
}

func GetBitU8(buf []byte, startBitN int, l int) byte {
	return byte(GetBitU64(buf, startBitN, l))
}

// 注 1：符号数值表示记录数据的符号和数值。最高有效位 MSB 为 0 表示正数，为 1 表示负数，其余位是数据的数值。
func GetBitG(buf []byte, startBitN int, l int) float64 {
	rval := float64(GetBitU(buf, startBitN+1, l-1))
	if GetBitU(buf, startBitN, 1) == 0 {
		return rval
	} else {
		return -rval
	}

}

func GetBitU16(buf []byte, startBitN int, l int) uint16 {
	return uint16(GetBitU64(buf, startBitN, l))
}

func GetBitU64(buf []byte, startBitN int, l int) uint64 {
	var rval uint64 = 0
	for i := startBitN; i < startBitN+l; i++ {
		b := buf[i/8]
		n := (7 - i%8)
		b = byte(b >> byte(n))
		b = b & 1 // 获取最低位
		rval = rval<<1 + uint64(b)
	}
	return rval
}

func SetBitI8(buf []byte, startBitN int, l int, val int8) {
	SetBitI64(buf, startBitN, l, int64(val))
}

func SetBitI32(buf []byte, startBitN int, l int, val int32) {
	SetBitI64(buf, startBitN, l, int64(val))
}

func SetBitU32(buf []byte, startBitN int, l int, val uint32) {
	SetBitU64(buf, startBitN, l, uint64(val))
}

func SetBitU8(buf []byte, startBitN int, l int, val uint8) {
	SetBitU64(buf, startBitN, l, uint64(val))
}

func SetBitU16(buf []byte, startBitN int, l int, val uint16) {
	SetBitU64(buf, startBitN, l, uint64(val))
}

func SetBitI64(buf []byte, startBitN int, l int, val int64) {
	if val < 0 {
		val |= I64_1 << uint8(l-1)
	} else {
		val &= ^(I64_1 << uint8(l-1))
	}
	SetBitU64(buf, startBitN, l, uint64(val))
}

func SetBitU64(buf []byte, startBitN int, l int, val uint64) {
	if l <= 0 || 64 < l {
		return
	}
	mask := U64_1 << (uint64(l) - 1)
	for i := startBitN; i < startBitN+l; i++ {
		bitN := uint8(7 - i%8)
		v := buf[i/8]
		m := byte(U64_1 << bitN)
		if val&mask > 0 {
			buf[i/8] = v | m
		} else {
			buf[i/8] &= ^m
		}
		mask >>= 1
	}
}

func UInt32_LEBytes(val uint32) []byte {
	buf := make([]byte, 4)
	binary.LittleEndian.PutUint32(buf, val)
	return buf
}

func UInt16_LEBytes(val uint16) []byte {
	buf := make([]byte, 2)
	binary.LittleEndian.PutUint16(buf, val)
	return buf
}

func UInt32_BEBytes(val uint32) []byte {
	buf := make([]byte, 4)
	binary.BigEndian.PutUint32(buf, val)
	return buf
}

func UInt32_FromBEBytes(buf []byte) uint32 {
	return binary.BigEndian.Uint32(buf)
}

func UInt16_FromBEBytes(buf []byte) uint16 {
	return binary.BigEndian.Uint16(buf)
}

func UInt16_FromLEBytes(buf []byte) uint16 {
	return binary.LittleEndian.Uint16(buf)
}

func UInt16_BEBytes(val uint16) []byte {
	buf := make([]byte, 2)
	binary.BigEndian.PutUint16(buf, val)
	return buf
}

/*
**

	0xAABBCCDDEEFF => 0000AABBCCDDEEFF
*/
func UInt64_BEBytes(val uint64) []byte {
	buf := make([]byte, 8)
	binary.BigEndian.PutUint64(buf, val)
	return buf
}

func Int64_BEBytes(val int64) []byte {
	return UInt64_BEBytes(uint64(val))
}

func UInt64_FromBEBytes(val []byte) uint64 {
	return binary.BigEndian.Uint64(val)
}

func Int64_FromBEBytes(val []byte) int64 {
	return int64(UInt64_FromBEBytes(val))
}

/*
*
保留后面的N 位

	BitTrimPrefix(binary: 100110, 3)=binary: 110;
*/
func BitTrimPrefix(v uint64, bitN byte) uint64 {
	mask0 := U64_MAX << (64 - bitN) >> (64 - bitN)
	return v & mask0
}

/*
**

	和 = rtklib exsign
	1: 保留bitN位
	2: 最高位为1还是0   1:为负数, 0:为正数
*/
func IntFromU(v uint64, bitN byte) int64 {
	// 保留N位
	v = BitTrimPrefix(v, bitN)
	flag := GetBitValue0(v, bitN-1) // 取最高位
	if flag > 0 {
		s0 := U64_MAX << bitN
		return int64(v | s0)
	} else {
		return int64(v)
	}
}

// =========================================
/***
  位为1的数量
*/
func GetBitOnU32(v uint32) (n byte) {
	for i := 0; i < 32; i++ {
		if v&1 == 1 {
			n++
		}
		v >>= 1
	}
	return n
}

func GetBitOnU64(v uint64) (n byte) {
	for i := 0; i < 64; i++ {
		if v&1 == 1 {
			n++
		}
		v >>= 1
	}
	return n
}

/*
**

	获取v 的位数 的值
	binary: 0010 1101
	GetU64BitsU(v, 2, 3) = binary: 11

	从startBit到endBit 包含endBit

	startBit 从0开始计数
*/
func GetU64BitsU(v uint64, startBit, endBit int) uint64 {
	v <<= (63 - endBit)
	v >>= (63 - endBit) + startBit
	return v
}

/*
**

	从startBit开始数 l位的值
*/
func GetU64BitsU_L(v uint64, startBit, l int) uint64 {
	return GetU64BitsU(v, startBit, startBit+l-1)
}

/*
*
从0开始
*/
func GetBitV_U32(v uint32, bitN byte) byte {
	return byte((v >> bitN) & 1)
}

func GetBitV_U64(v uint64, bitN byte) byte {
	return byte((v >> bitN) & 1)
}

func bytes_grow(buf []byte, n int) []byte {
	newBuf := make([]byte, len(buf), 2*cap(buf)+n)
	copy(newBuf, buf)
	return newBuf
}

// Grow grows b's capacity, if necessary, to guarantee space for
// another n bytes. After Grow(n), at least n bytes can be written to b
// without another allocation. If n is negative, Grow panics.
func BytesCheckGrow(buf []byte, n int) []byte {
	if n < 0 {
		panic("utils.BytesBuilder.Grow: negative count")
	}
	if cap(buf)-len(buf) < n {
		return bytes_grow(buf, n)
	}
	return buf
}

func BytesCheckSize(buf []byte, start, l int) []byte {
	if start < 0 {
		for i := 0; i < l; i++ {
			buf = append(buf, 0)
		}
		return buf
	}
	n := (start + l) - len(buf)
	if n <= 0 {
		return buf
	}

	for i := 0; i < n; i++ {
		buf = append(buf, 0)
	}
	return buf
}

func BytesAppendUInt64_LE(buf []byte, v uint64) []byte {
	newBuf := BytesCheckGrow(buf, 8)
	newBuf = BytesCheckSize(newBuf, -1, 8)
	binary.LittleEndian.PutUint64(newBuf, v)
	return newBuf
}

// 读取指定长度的数据, 直到返回错误或者读取完成
// l:=0 表示读取buf的长度
func ReadLBytes(r io.Reader, buf []byte, l int) error {
	if l == 0 || l > len(buf) {
		l = len(buf)
	}
	n0 := 0
	for {
		n, err := r.Read(buf[n0:l])
		if err != nil {
			return err
		}
		n0 += n
		if n0 == l {
			return nil
		}
	}
}

func RangeByteFromHexStr(hexstr string, cb func(v byte) bool) int {
	hexstr = strings.Replace(hexstr, " ", "", -1)
	hexstr = strings.Replace(hexstr, "\r", "", -1)
	hexstr = strings.Replace(hexstr, "\n", "", -1)
	hexstrArr := []rune(hexstr)
	l := len(hexstrArr)

	i := 0

	for {
		if (i + 1) >= l {
			break
		}
		if IsHexChar(hexstrArr[i]) && IsHexChar(hexstrArr[i+1]) {
			v := byte(HexValue(hexstrArr[i])<<4 + HexValue(hexstrArr[i+1]))
			i += 2
			if !cb(v) {
				break
			}
		} else {
			break
		}
	}
	return i / 2

}

func IsHexChar(chr rune) bool {
	c := byte(chr)
	return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')
}

func HexStrToBuf(hexstr string) []byte {
	hexstr = strings.Replace(hexstr, " ", "", -1)
	hexstr = strings.Replace(hexstr, "\t", "", -1)
	hexstr = strings.Replace(hexstr, "\r", "", -1)
	hexstr = strings.Replace(hexstr, "\n", "", -1)
	hexstrArr := []rune(hexstr)
	l := len(hexstrArr)
	l2 := l >> 1

	rval := make([]byte, 0, l2)
	i := 0

	for {
		if (i + 1) >= l {
			break
		}
		if IsHexChar(hexstrArr[i]) && IsHexChar(hexstrArr[i+1]) {
			v := HexValue(hexstrArr[i])<<4 + HexValue(hexstrArr[i+1])
			i += 2
			rval = append(rval, byte(v))
		} else {
			break
		}
	}
	return rval

}

func HexValue(chr rune) int {
	c := int(chr)
	if (c >= '0') && (c <= '9') {
		return c - '0'
	} else if c >= 'a' && c <= 'f' {
		return 10 + c - 'a'
	} else {
		return 10 + c - 'A'
	}
}

func HexToInt(hex string) int {
	r := 0
	for _, char := range []rune(hex) {
		r = r<<4 + HexValue(char)
	}
	return r
}

// / 设置位上的值
// / SetBitValue(0, 2, true) = 二进制(10)
func SetBitValue(ival uint64, bitN byte, bitVal bool) uint64 {
	bitN = bitN - 1
	if bitVal {
		ival = ival | (U64_1 << bitN)
	} else {
		x := (U64_1 << bitN)
		x = x ^ U64_MAX
		ival = ival & x
	}
	return ival
}

/*
**

	bitN 从0开始
	cmpbitVal, newbitVal, 只能是0或者1
	比较低bitN是否为cmpbitval, 如果是则进行设置为newbitval
	changed :true, 表示有修改
*/
func CmpAndSetBitValue(ival uint64, bitN byte, cmpbitVal, newbitVal byte) (changed bool, newval uint64) {
	mask := (U64_1 << bitN)
	r0 := ival & mask // 大于0表示 该位为1, 否则为0
	if r0 > 0 && cmpbitVal == 0 {
		return false, ival
	}

	if r0 == 0 && cmpbitVal != 0 {
		return false, ival
	}

	if newbitVal > 0 {
		ival = ival | mask
	} else {
		x := mask
		x = x ^ U64_MAX
		ival = ival & x
	}
	return true, ival
}

// / 设置位上的值  0:位第一位
// / SetU8BitValue0(0, 1, true) = 二进制(10)
func SetU8BitValue0(ival byte, bitN byte, bitVal bool) byte {
	if bitVal {
		ival = ival | (U8_1 << bitN)
	} else {
		x := (U8_1 << bitN)
		x = x ^ U8_MAX
		ival = ival & x
	}
	return ival
}

func GetU8BitValue0(ival byte, bitN byte) byte {
	rval := ival & (U8_1 << bitN)
	if rval > 0 {
		return 1
	} else {
		return 0
	}
}

// / 设置位上的值  0:位第一位
// / SetBitValue(0, 1, true) = 二进制(10)
func SetBitValue0(ival uint64, bitN byte, bitVal bool) uint64 {
	if bitVal {
		ival = ival | (U64_1 << bitN)
	} else {
		x := (U64_1 << bitN)
		x = x ^ U64_MAX
		ival = ival & x
	}
	return ival
}

// 0:位第一位
func GetBitValue0(ival uint64, bitN byte) byte {
	rval := ival & (U64_1 << bitN)
	if rval > 0 {
		return 1
	} else {
		return 0
	}
}

// 1:位第一位
func GetBitValue(ival uint64, bitN byte) byte {
	// Result := pvByte and (1 shl pvOffset) shr pvOffset;
	bitN = bitN - 1
	rval := ival & (U64_1 << bitN) >> bitN
	return byte(rval)
}

// / <summary>
// /   HEX转成10进制
// /   HEX中不能有字母
// /   0x65036  -> 65036
// / </summary>
func HEX2BCD(val int) (int, error) {
	var i, j, rval int
	i = 0
	rval = 0
	for {
		j = val % 16
		if j > 9 {
			return -1, errors.New(fmt.Sprintf("HEX2BCD: %d 必须小于10", j))
		}

		rval = j*int(math.Trunc(math.Pow(10, float64(i)))) + rval

		// 商
		val = val / 16
		if val == 0 {
			break
		}

		i++
	}
	return rval, nil
}

func HEX2BCDDef(val, def int) int {
	var i, j, rval int
	i = 0
	rval = 0
	for {
		j = val % 16
		if j > 9 {
			return def
		}

		rval = j*int(math.Trunc(math.Pow(10, float64(i)))) + rval

		// 商
		val = val / 16
		if val == 0 {
			break
		}

		i++
	}
	return rval
}

// 预定义十六进制字符映射表（小写）
var hexTable = [16]byte{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}

// BufToHexStr 将字节缓冲区转换为十六进制字符串，支持自定义分隔符
// buf: 输入字节数组
// l: 需要转换的长度（从buf[0]开始）
// spliterstr: 每个字节的十六进制表示之间的分隔符（如空格、":"等）
func BufToHexStr(buf []byte, l int, spliterstr string) string {
	// 处理边界情况
	if l < 0 || len(buf) == 0 || l > len(buf) {
		return ""
	}

	if l == 0 {
		l = len(buf)
	}

	spliter := []byte(spliterstr)
	spliterLen := len(spliter)

	// 计算目标缓冲区大小：每个字节2个十六进制字符 + 分隔符总长度
	totalLen := l * 2
	if spliterLen > 0 && l > 1 {
		totalLen += spliterLen * (l - 1)
	}

	// 预分配精确大小的缓冲区
	dst := make([]byte, 0, totalLen)

	// 处理第一个字节
	dst = append(dst, hexTable[buf[0]>>4], hexTable[buf[0]&0x0f])

	// 处理剩余字节（带分隔符）
	for i := 1; i < l; i++ {
		// 添加分隔符
		if spliterLen > 0 {
			dst = append(dst, spliter...)
		}
		// 添加当前字节的十六进制表示
		dst = append(dst, hexTable[buf[i]>>4], hexTable[buf[i]&0x0f])
	}

	// 直接转换为字符串，避免额外分配
	return *(*string)(unsafe.Pointer(&dst))
}
